package com.foruo.simple.rpc.provider;

import com.foruo.simple.rpc.service.IDemoService;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 接口提供者
 * @author GaoYuan
 */
public class ProviderStarter {

    public static void main(String[] args){
        try {
            // 搭建 8080 端口的socket监听服务
            ServerSocket serverSocket = new ServerSocket(8989);
            while (true){
                Socket socket = serverSocket.accept();
                // 获取socket的输入流（即其他服务进行请求的参数，主要是获取调用的类名、方法名、参数等）
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());

                String className = objectInputStream.readUTF();
                System.out.println(">>>>>> [接收]：" + className);
                String methodName = objectInputStream.readUTF();
                System.out.println(">>>>>> [接收]：" + methodName);
                Class[] methodParameterTypes = (Class[]) objectInputStream.readObject();
                System.out.println(">>>>>> [接收]：" + methodParameterTypes);
                Object[] methodArgs = (Object[]) objectInputStream.readObject();
                System.out.println(">>>>>> [接收]：" + methodArgs);

                Class myclass = null;

                // 这里主要是解决如何通过接收到的类名为"IDemoService" 转换为 具体的实现"DemoService"
                if(IDemoService.class.getName().equals(className)){
                    // 此时 myclass已经是具体的实现类了
                    myclass = ClassLoader.getSystemClassLoader().loadClass("com.foruo.simple.rpc.provider.DemoService");
//                    myclass = DemoService.class; // 也可以用这种方式获取class
                    System.out.println(">>>>>> [组装]：指定实现类DemoService");
                }

                // 获取具体实现类的方法
                Method method = myclass.getMethod(methodName, methodParameterTypes);
                System.out.println(">>>>>> [组装]：指定方法");
                // 获取实现类方法执行的结果
                Object invoke = method.invoke(myclass.newInstance(), methodArgs);
                System.out.println(">>>>>> [执行]：指定实现类的指定方法");
                System.out.println(">>>>>> [执行]：获取方法执行结果");
                System.out.println(">>>>>> [回执]：将执行结果输出");
                // 将执行结果输出
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                objectOutputStream.writeObject(invoke);
                objectOutputStream.flush();

                // 关闭流
                objectInputStream.close();
                objectOutputStream.close();
                // 关闭socket
                socket.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
